---
title: Returns Item Properties (Similar Product)
---

<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

You can modify the [default DataSource](dase.html#data) to read your custom properties or different Entity Type.

This explains how to add user defined properties to items returned by your engine. We add properties "title", "date" and "imdbUrl" for entity type "item".

You can find the complete modified source code [here](https://github.com/apache/predictionio/tree/develop/examples/scala-parallel-similarproduct/return-item-properties).

>> Note: you also need import events with these properties accordingly.

## Modification

### DataSource.scala

- modify the `Item` parameters
- modify how to create the `Item` object using the entity properties

```scala

// MODIFIED
case class Item(
     title: String,
     date: String,
     imdbUrl: String,
     categories: Option[List[String]])

...

  override
  def readTraining(sc: SparkContext): TrainingData = {
    ...
    // create a RDD of (entityID, Item)
    val itemsRDD: RDD[(String, Item)] = PEventStore.aggregateProperties(
      appName = dsp.appName,
      entityType = "item"
    )(sc).map { case (entityId, properties) =>
      val item = try {
        // Assume categories is optional property of item.
        // MODIFIED
        Item(
          title = properties.get[String]("title"),
          date = properties.get[String]("date"),
          imdbUrl = properties.get[String]("imdbUrl"),
          categories = properties.getOpt[List[String]]("categories"))
      } catch {
        case e: Exception => {
          logger.error(s"Failed to get properties ${properties} of" +
            s" item ${entityId}. Exception: ${e}.")
          throw e
        }
      }
      (entityId, item)
    }.cache()

    ...
  }
```

### Engine.scala

Modify the `ItemScore` parameters too.

```scala
// MODIFIED
case class ItemScore(
  item: String,
  title: String,
  date: String,
  imdbUrl: String,
  score: Double
) extends Serializable
```

### ALSAlgorithm.scala

Modify how to create the ItemScore object using the properties.

```scala

  def predict(model: ALSModel, query: Query): PredictedResult = {
    ...

    val itemScores = topScores.map { case (i, s) =>
      // MODIFIED
      val it = model.items(i)
      ItemScore(
        item = model.itemIntStringMap(i),
        title = it.title,
        date = it.date,
        imdbUrl = it.imdbUrl,
        score = s
      )
    }

    ...
  }

```

Using `model.items(i)` you can receive corresponding object of the `Item` class, and now you can access its properties which you created during previous step.

### Test the Result

Then we can build/train/deploy the engine and test the result:

The query

```bash
$ curl -H "Content-Type: application/json" \
-d '{ "items": ["i1"], "num": 4 }' \
http://localhost:8000/queries.json
```

will return the result

```json
{
  "itemScores":[
    {"item":"i3","title":"title for movie i3","date":"1947","imdbUrl":"http://imdb.com/fake-url/i3","score":0.5865418718902017},
    {"item":"i44","title":"title for movie i44","date":"1941","imdbUrl":"http://imdb.com/fake-url/i44","score":0.5740199916714374},
    {"item":"i37","title":"title for movie i37","date":"1940","imdbUrl":"http://imdb.com/fake-url/i37","score":0.5576820095310056},
    {"item":"i6","title":"title for movie i6","date":"1947","imdbUrl":"http://imdb.com/fake-url/i6","score":0.45856345689769473}
  ]
}
```

That's it! Your engine can return more information.
